﻿﻿﻿﻿﻿﻿﻿﻿﻿﻿﻿﻿﻿﻿﻿﻿﻿using DeviceCommons.DataHandling;
using DeviceCommons.DataHandling;
using DeviceCommons.DataHandling.Compression;
using DeviceCommons.DeviceMessages.Enums;
using DeviceCommons.DeviceMessages.Models;
using DeviceCommons.DeviceMessages.Models.V1;
using DeviceCommons.DeviceMessages.Serialization;
using DeviceCommons.Security;
using DeviceCommons.Validation;
using Microsoft.Extensions.Options;
using System.Buffers;
using System.Collections.Frozen;

namespace DeviceCommons.DeviceMessages.Builders
{
    public class DeviceMessageBuilder : IDeviceMessageBuilder
    {
        private readonly DeviceMessage _message = new();
        private DeviceInfoBuilder? _currentDeviceBuilder;
        private readonly IDeviceMessageSerializer _serializer;
        private readonly IDeviceMessageParser _parser;
        private readonly IDeviceCommonsConfigurationService? _configService;

        /// <summary>
        /// DI构造器
        /// </summary>
        /// <param name="serializer">消息序列化器</param>
        /// <param name="parser">消息解析器</param>
        /// <param name="configService">配置服务</param>
        public DeviceMessageBuilder(
            IDeviceMessageSerializer serializer,
            IDeviceMessageParser parser,
            IDeviceCommonsConfigurationService? configService = null)
        {
            _serializer = serializer;
            _parser = parser;
            _configService = configService;

            // 应用配置选项
            ApplyConfiguration();
        }

        /// <summary>
        /// 默认构造器（向后兼容）
        /// </summary>
        public DeviceMessageBuilder()
        {
            // 为每个实例创建独立的序列化器和解析器，避免静态状态污染
            _serializer = new DeviceMessageSerializer();
            _parser = new DeviceMessageParser();
            
            // 配置默认解密函数
            _parser.DecryptFunc = cipherText => DeviceMessageUtilities.AES.Value.Decrypt(cipherText, DeviceMessageArrayPool.DefaultAedPassword);
        }

        private void ApplyConfiguration()
        {
            if (_configService == null) return;

            // 应用加密解密函数
            if (_configService.EncryptFunc != null)
            {
                _serializer.EncryptFunc = _configService.EncryptFunc;
            }

            if (_configService.DecryptFunc != null)
            {
                _parser.DecryptFunc = _configService.DecryptFunc;
            }

            var options = _configService.CurrentOptions;

            // 应用压缩解压函数
            if (options.CompressFunc != null || options.EnableDefaultGZipCompression)
            {
                // 创建适配器函数，将byte[]转换为string进行处理
                _serializer.CompressFunc = data =>
                {
                    if (options.CompressFunc != null)
                    {
                        // 使用自定义压缩函数
                        return options.CompressFunc(data);
                    }
                    else if (options.EnableDefaultGZipCompression)
                    {
                        // 使用默认GZip压缩
                        return DeviceMessageUtilities.GZIP.Compress(data);
                    }
                    return data; // 默认返回原数据
                };
            }

            if (options.DecompressFunc != null || options.EnableDefaultGZipCompression)
            {
                // 创建适配器函数，将string转换为byte[]进行处理
                _parser.DecompressFunc = data =>
                {
                    if (options.DecompressFunc != null)
                    {
                        // 使用自定义解压函数
                        return options.DecompressFunc(data);
                    }
                    else if (options.EnableDefaultGZipCompression)
                    {
                        // 使用默认GZip解压
                        return DeviceMessageUtilities.GZIP.Decompress(data);
                    }
                    return data; // 默认返回原数据
                };
            }
        }

        public static IDeviceMessageBuilder Create() => new DeviceMessageBuilder();

        public IDeviceMessageBuilder WithHeader(
            byte version = 0x02,
            CRCTypeEnum crcType = CRCTypeEnum.CRC16,
            TimeStampFormatEnum timeFormat = TimeStampFormatEnum.MS,
            HeaderValueTypeEnum valueType = HeaderValueTypeEnum.Standard)
        {
            _message.Header = new DeviceMessageHeader
            {
                Version = version,
                CRCType = crcType,
                TimeStampFormat = timeFormat,
                ValueType = valueType
            };
            return this;
        }

        public IDeviceMessageBuilder WithVersion(byte version)
        {
            _message.Header ??= new DeviceMessageHeader();
            _message.Header.Version = version;
            return this;
        }

        public IDeviceMessageBuilder WithMainDevice(string did, byte deviceType)
        {
            return WithMainDevice(did, deviceType, _ => { });
        }

        public IDeviceMessageBuilder WithMainDevice(string did, byte deviceType, Action<DeviceInfoBuilder> config)
        {
            // 前置验证
            DeviceMessageValidator.ValidateDeviceId(did, nameof(did));
            DeviceMessageValidator.ValidateDeviceType(deviceType);
            ArgumentNullException.ThrowIfNull(config, nameof(config));

            var device = new DeviceMessageInfo
            {
                DID = did,
                DeviceType = deviceType
            };

            _currentDeviceBuilder = new DeviceInfoBuilder(device);
            config(_currentDeviceBuilder);
            // Don't build immediately - keep builder for potential additional readings
            return this;
        }

        public IDeviceMessageBuilder WithChildDevice(string did, byte deviceType, Action<DeviceInfoBuilder> config)
        {
            // 前置验证
            DeviceMessageValidator.ValidateDeviceId(did, nameof(did));
            DeviceMessageValidator.ValidateDeviceType(deviceType);
            DeviceMessageValidator.ValidateChildDevicePrerequisites(_currentDeviceBuilder != null);
            ArgumentNullException.ThrowIfNull(config, nameof(config));

            var device = new DeviceMessageInfo
            {
                DID = did,
                DeviceType = deviceType
            };

            var builder = new DeviceInfoBuilder(device);
            config(builder);

            _message.ChildDevice ??= new DeviceMessageChild();
            
            // 验证设备数量限制（主设备 + 已有子设备 + 当前子设备）
            var currentDeviceCount = 1 + (_message.ChildDevice.Count) + 1;
            DeviceMessageValidator.ValidateDeviceCount(currentDeviceCount);
            
            _message.ChildDevice.AddOrUpdateChild(builder.Build());

            return this;
        }

        public IDeviceMessageBuilder WithEncryption(
            Func<string, string>? encryptFunc = null,
            Func<string, string>? decryptFunc = null)
        {
            // 前置验证加密参数
            DeviceMessageValidator.ValidateEncryptionParameters(encryptFunc, decryptFunc, null);
            
            _parser.DecryptFunc = decryptFunc;
            _serializer.EncryptFunc = encryptFunc;
            return this;
        }

        public IDeviceMessageBuilder WithAesEncryption() => WithAesEncryption(DeviceMessageArrayPool.DefaultAedPassword);

        public IDeviceMessageBuilder WithAesEncryption(string password)
        {
            // 前置验证密码
            DeviceMessageValidator.ValidatePassword(password, nameof(password));
            
            return WithEncryption(
                plainText => DeviceMessageUtilities.AES.Value.Encrypt(plainText, password),
                cipherText => DeviceMessageUtilities.AES.Value.Decrypt(cipherText, password)
            );
        }
        
        /// <summary>
        /// 使用AES加密，并指定加密模式
        /// </summary>
        /// <param name="password">加密密码</param>
        /// <param name="mode">AES加密模式（快速模式或安全模式）</param>
        /// <returns>当前构建器实例</returns>
        public IDeviceMessageBuilder WithAesEncryption(string? password, AesMode mode)
        {
            // 前置验证密码
            DeviceMessageValidator.ValidatePassword(password, nameof(password));
            
            // 根据模式创建相应的AES加密器
            var aes = mode switch
            {
                AesMode.Fast => AesEncryptor.CreateFastMode(),
                AesMode.Secure => AesEncryptor.CreateSecureMode(),
                _ => AesEncryptor.CreateFastMode() // 默认使用快速模式
            };
            
            return WithEncryption(
                plainText => aes.Encrypt(plainText, password),
                cipherText => aes.Decrypt(cipherText, password)
            );
        }
        
        /// <summary>
        /// 使用AES快速模式加密（1000次PBKDF2迭代，启用缓存）
        /// </summary>
        /// <param name="password">加密密码</param>
        /// <returns>当前构建器实例</returns>
        public IDeviceMessageBuilder WithFastAesEncryption(string password)
        {
            return WithAesEncryption(password, AesMode.Fast);
        }
        
        /// <summary>
        /// 使用AES安全模式加密（60000次PBKDF2迭代，禁用缓存）
        /// </summary>
        /// <param name="password">加密密码</param>
        /// <returns>当前构建器实例</returns>
        public IDeviceMessageBuilder WithSecureAesEncryption(string password)
        {
            return WithAesEncryption(password, AesMode.Secure);
        }

        /// <summary>
        /// 配置自定义加密方法但使用默认密码
        /// 这种情况下，自定义加密函数内部应该使用默认密码
        /// </summary>
        /// <param name="customEncryptFunc">自定义加密函数，接收(plainText, defaultPassword)参数</param>
        /// <param name="customDecryptFunc">自定义解密函数，接收(cipherText, defaultPassword)参数</param>
        /// <returns>当前构建器实例</returns>
        public IDeviceMessageBuilder WithCustomEncryptionUsingDefaultPassword(
            Func<string, string, string> customEncryptFunc,
            Func<string, string, string> customDecryptFunc)
        {
            var defaultPassword = DeviceMessageArrayPool.DefaultAedPassword;
            return WithEncryption(
                plainText => customEncryptFunc(plainText, defaultPassword),
                cipherText => customDecryptFunc(cipherText, defaultPassword)
            );
        }

        public IDeviceMessageBuilder WithGZipCompression()
        {
            return WithCompression(
                com => DeviceMessageUtilities.GZIP.Compress(com),
                dec => DeviceMessageUtilities.GZIP.Decompress(dec)
                );
        }

        public IDeviceMessageBuilder AddReading(short timeOffset, Action<DeviceInfoReadingBuilder> config)
        {
            if (_currentDeviceBuilder == null)
                throw new InvalidOperationException("No active device configuration");

            _currentDeviceBuilder.AddReading(timeOffset, config);
            return this;
        }

        public IDeviceMessageBuilder AddReading<T>(short timeOffset, byte sid, T value)
            where T : notnull
        {
            var type = _valueTypeMap.TryGetValue(typeof(T), out var t)
                       ? t
                       : (value is byte[]? StateValueTypeEnum.Binary : StateValueTypeEnum.String);

            AddReading(timeOffset, (sid, value, type));
            return this;
        }

        public IDeviceMessageBuilder AddReading(short timeOffset, byte sid, string value) =>
            AddReading(timeOffset, (sid, value, StateValueTypeEnum.String));

        public IDeviceMessageBuilder AddReading(short timeOffset, byte sid, byte[] value) =>
            AddReading(timeOffset, (sid, value, StateValueTypeEnum.Binary));

        public IDeviceMessageBuilder AddReading(short timeOffset, params (byte sid, object? value, StateValueTypeEnum? type)[] states)
        {
            if (_currentDeviceBuilder == null)
                throw new InvalidOperationException("No active device configuration");

            _currentDeviceBuilder.AddReading(timeOffset, reading =>
            {
                foreach (var (sid, value, type) in states)
                {
                    reading.AddState(sid, value, type ?? InferType(value));
                }
            });

            return this;
        }

        public IDeviceMessage Build()
        {
            // 前置验证主设备是否存在
            DeviceMessageValidator.ValidateMainDeviceExists(_currentDeviceBuilder != null);

            _message.Header ??= new DeviceMessageHeader();

            _message.MainDevice = _currentDeviceBuilder!.Build();

            return _message;
        }

        public byte[] BuildBytes()
        {
            var arrayBufferWriter = new ArrayBufferWriter<byte>();
            _serializer.Serializer(arrayBufferWriter, Build());
            return arrayBufferWriter.WrittenSpan.ToArray();
        }

        public string BuildHex(bool compress = false, bool encrypt = false)
        {
            var arrayBufferWriter = new ArrayBufferWriter<byte>();
            return _serializer.Serializer(arrayBufferWriter, Build(), encrypt, compress);
        }

        /// <summary>
        /// 构建十六进制字符串，支持自定义加密密码
        /// </summary>
        /// <param name="compress">是否压缩</param>
        /// <param name="encrypt">是否加密</param>
        /// <param name="encryptionPassword">加密密码，null时使用默认密码或预设的加密函数</param>
        /// <returns>十六进制字符串</returns>
        public string BuildHex(bool compress, bool encrypt, string? encryptionPassword)
        {
            // 前置验证密码（如果提供）
            if (encryptionPassword != null)
            {
                DeviceMessageValidator.ValidatePassword(encryptionPassword, nameof(encryptionPassword));
            }
            
            var arrayBufferWriter = new ArrayBufferWriter<byte>();
            return _serializer.Serializer(arrayBufferWriter, Build(), encrypt, compress, encryptionPassword);
        }

        public async Task<byte[]> BuildBytesAsync(CancellationToken cancellationToken = default)
        {
            var arrayBufferWriter = new ArrayBufferWriter<byte>();
            await _serializer.SerializerAsync(arrayBufferWriter, Build(), cancellationToken).ConfigureAwait(false);
            return arrayBufferWriter.WrittenSpan.ToArray();
        }

        public async Task<string> BuildHexAsync(bool compress = false, bool encrypt = false, CancellationToken cancellationToken = default) =>
            await _serializer.SerializerAsync(
                new ArrayBufferWriter<byte>(), Build(), encrypt, compress, cancellationToken).ConfigureAwait(false);

        /// <summary>
        /// 异步构建十六进制字符串，支持自定义加密密码
        /// </summary>
        /// <param name="compress">是否压缩</param>
        /// <param name="encrypt">是否加密</param>
        /// <param name="encryptionPassword">加密密码，null时使用默认密码或预设的加密函数</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>十六进制字符串</returns>
        public async Task<string> BuildHexAsync(bool compress, bool encrypt, string? encryptionPassword, CancellationToken cancellationToken = default) =>
            await _serializer.SerializerAsync(
                new ArrayBufferWriter<byte>(), Build(), encrypt, compress, encryptionPassword, cancellationToken).ConfigureAwait(false);

        public IDeviceMessageBuilder WithEncryptFunc(Func<string, string> encryptFunc)
        {
            _serializer.EncryptFunc = encryptFunc;
            return this;
        }

        public IDeviceMessageBuilder WithDecryptFunc(Func<string, string> decryptFunc)
        {
            _parser.DecryptFunc = decryptFunc;
            return this;
        }

        /// <summary>
        /// 配置自定义压缩和解压方法
        /// </summary>
        /// <param name="compressFunc">自定义压缩方法，用于序列化时压缩数据</param>
        /// <param name="decompressFunc">自定义解压方法，用于解析时解压数据</param>
        /// <returns>当前构建器实例，支持链式调用</returns>
        public IDeviceMessageBuilder WithCompression(
            Func<byte[], byte[]>? compressFunc = null,
            Func<byte[], byte[]>? decompressFunc = null)
        {
            _serializer.CompressFunc = compressFunc;
            _parser.DecompressFunc = decompressFunc;
            return this;
        }

        /// <summary>
        /// 配置自定义压缩方法
        /// </summary>
        /// <param name="compressFunc">自定义压缩方法，用于序列化时压缩数据</param>
        /// <returns>当前构建器实例，支持链式调用</returns>
        public IDeviceMessageBuilder WithCompressFunc(Func<byte[], byte[]> compressFunc)
        {
            _serializer.CompressFunc = compressFunc;
            return this;
        }

        /// <summary>
        /// 配置自定义解压方法
        /// </summary>
        /// <param name="decompressFunc">自定义解压方法，用于解析时解压数据</param>
        /// <returns>当前构建器实例，支持链式调用</returns>
        public IDeviceMessageBuilder WithDecompressFunc(Func<byte[], byte[]> decompressFunc)
        {
            _parser.DecompressFunc = decompressFunc;
            return this;
        }

        private static StateValueTypeEnum InferType(object? value)
        {
            if (value == null)
                return StateValueTypeEnum.String;

            // 更严格的类型检查
            var valueType = value.GetType();

            // 优先使用类型映射字典
            if (_valueTypeMap.TryGetValue(valueType, out var mappedType))
                return mappedType;

            // 备用模式匹配
            return value switch
            {
                float => StateValueTypeEnum.Float32,
                double => StateValueTypeEnum.Double,
                int => StateValueTypeEnum.Int32,
                short => StateValueTypeEnum.Int16,
                ushort => StateValueTypeEnum.UInt16,
                bool => StateValueTypeEnum.Bool,
                ulong => StateValueTypeEnum.Timestamp,
                byte[] => StateValueTypeEnum.Binary,
                _ => StateValueTypeEnum.String
            };
        }

        private static readonly FrozenDictionary<Type, StateValueTypeEnum> _valueTypeMap =
            new Dictionary<Type, StateValueTypeEnum>
            {
                [typeof(float)] = StateValueTypeEnum.Float32,
                [typeof(int)] = StateValueTypeEnum.Int32,
                [typeof(short)] = StateValueTypeEnum.Int16,
                [typeof(ushort)] = StateValueTypeEnum.UInt16,
                [typeof(bool)] = StateValueTypeEnum.Bool,
                [typeof(double)] = StateValueTypeEnum.Double,
                [typeof(ulong)] = StateValueTypeEnum.Timestamp,
            }.ToFrozenDictionary();
    }
}
